﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Aribaccio.Security
{
    /// <summary>
    /// 可逆 AES 加密解密算法
    /// </summary>
    [ComVisible(true)]
    [ComSourceInterfaces(typeof(ISecurity))]
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    public class SecurityAES : ISecurity
    {
        /// <summary>
        /// 默认安全密钥，密钥必须为32位字符[安全密钥-公共-软件类库-加解密钥1]
        /// </summary>
        protected string DefaultSecretKey = "SECRET-COMMON-SOFTLB-CRYPTO-KEY1";
        /// <summary>
        /// 用于对称算法的初始化向量
        /// </summary>
        protected byte[] DefaultSecretRgbIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
        /// <summary>
        /// 默认安全密钥，密钥必须为32位字符
        /// </summary>
        public string SecretKey { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public SecurityAES()
        {
            this.SecretKey = string.Empty;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="argSecretKey">默认安全密钥，密钥必须为32位字符</param>
        public SecurityAES(string argSecretKey)
        {
            this.SecretKey = argSecretKey;
        }

        /// <summary>
        /// AES 加密(高级加密标准，是下一代的加密算法标准，速度快，安全级别高，目前 AES 标准的一个实现是 Rijndael 算法)
        /// </summary>
        /// <param name="argEncryptString">待加密明文</param>
        /// <returns>加密密文字符串</returns>
        public string Encrypt(string argEncryptString)
        {
            //检查，密文不得为空
            if (string.IsNullOrEmpty(argEncryptString)) { return string.Empty; }
            //检查，密钥必须为32位
            if (string.IsNullOrWhiteSpace(this.SecretKey)) { this.SecretKey = DefaultSecretKey; }
            if (this.SecretKey.Length != 32) { return string.Empty; }
           
            string resultEncrypt = "";
            Aes aesProvider = Aes.Create();
            try
            {
                byte[] encryptBytes = Encoding.Default.GetBytes(argEncryptString);
                MemoryStream mStream = new MemoryStream();
                //CreateDecryptor的参数：rgbKey：byte[32] , rgbIV：byte[16] 
                CryptoStream cStream = new CryptoStream(mStream, aesProvider.CreateEncryptor(Encoding.Default.GetBytes(this.SecretKey), DefaultSecretRgbIV), CryptoStreamMode.Write);
                cStream.Write(encryptBytes, 0, encryptBytes.Length);
                cStream.FlushFinalBlock();
                resultEncrypt = Convert.ToBase64String(mStream.ToArray());
                cStream.Close(); cStream.Dispose();
                mStream.Close(); mStream.Dispose();
            }
            catch (IOException) { resultEncrypt = string.Empty; }
            catch (CryptographicException) { resultEncrypt = string.Empty; }
            catch (ArgumentException) { resultEncrypt = string.Empty; }
            catch (Exception) { resultEncrypt = string.Empty; }
            finally { aesProvider.Clear(); }
            return resultEncrypt;
        }

        /// <summary>
        /// AES 解密(高级加密标准，是下一代的加密算法标准，速度快，安全级别高，目前 AES 标准的一个实现是 Rijndael 算法)
        /// </summary>
        /// <param name="argDecryptString">待解密密文</param>
        /// <returns>解密明文字符串</returns>
        public string Decrypt(string argDecryptString)
        {
            //检查，密文不得为空
            if (string.IsNullOrEmpty(argDecryptString)) { return string.Empty; }
            //检查，密钥必须为32位
            if (string.IsNullOrWhiteSpace(this.SecretKey)) { this.SecretKey = DefaultSecretKey; }
            if (this.SecretKey.Length != 32) { return string.Empty; }
          
            string resultDecrypt = "";
            Aes aesProvider = Aes.Create();
            try
            {
                byte[] decryptBytes = Convert.FromBase64String(argDecryptString);
                MemoryStream mStream = new MemoryStream();
                //CreateDecryptor的参数：rgbKey：byte[32] , rgbIV：byte[16] 
                CryptoStream cStream = new CryptoStream(mStream, aesProvider.CreateDecryptor(Encoding.Default.GetBytes(this.SecretKey), DefaultSecretRgbIV), CryptoStreamMode.Write);
                cStream.Write(decryptBytes, 0, decryptBytes.Length);
                cStream.FlushFinalBlock();
                resultDecrypt = Encoding.Default.GetString(mStream.ToArray());
                cStream.Close();
                cStream.Dispose();
                mStream.Close();
                mStream.Dispose();
            }
            catch (IOException) { resultDecrypt = string.Empty; }
            catch (CryptographicException) { resultDecrypt = string.Empty; }
            catch (ArgumentException) { resultDecrypt = string.Empty; }
            catch (Exception) { resultDecrypt = string.Empty; }
            finally { aesProvider.Clear(); }
            return resultDecrypt;
        }
    }
}
